﻿using System.CommandLine;

namespace zijian666.CommandLine;
/// <summary>
/// 提供 <see cref="Command"/> 和 <see cref="RootCommand"/> 的扩展方法，
/// 用于简化命令绑定、添加及执行流程。
/// </summary>
public static class CommandLineExtensions
{
    /// <summary>
    /// 通过泛型类型 <typeparamref name="TCommand"/> 绑定命令到指定 <see cref="Command"/> 实例。
    /// </summary>
    /// <typeparam name="TCommand">要绑定的命令类型。</typeparam>
    /// <param name="command">目标命令对象。</param>
    /// <returns>绑定后的 <see cref="Command"/> 实例。</returns>
    public static Command BindCommand<TCommand>(this Command command)
    {
        return CommandLineBuilder.BuildCommand<TCommand>(command);
    }

    /// <summary>
    /// 通过泛型类型 <typeparamref name="TCommand"/> 创建命令并添加到指定 <see cref="Command"/> 实例。
    /// </summary>
    /// <typeparam name="TCommand">要添加的命令类型。</typeparam>
    /// <param name="command">父命令对象。</param>
    /// <returns>添加后的父 <see cref="Command"/> 实例。</returns>
    public static Command AddCommand<TCommand>(this Command command)
    {
        var cmd = CommandLineBuilder.BuildCommand<TCommand>(null);
        command.Add(cmd);
        return command;
    }

    /// <summary>
    /// 异步执行 <see cref="RootCommand"/>，根据返回值决定是否退出进程。
    /// </summary>
    /// <param name="root">根命令对象。</param>
    /// <returns>异步任务。</returns>
    public static async Task InvokeAsync(this RootCommand root)
    {
        var parseResult = ParseResult(root);
        var num = await parseResult.InvokeAsync();

        if (num == 0)
        {
            return;
        }
        Environment.Exit(num);
    }

    /// <summary>
    /// 解析命令行参数并返回 <see cref="ParseResult"/>。
    /// </summary>
    /// <param name="root">根命令对象。</param>
    /// <returns>解析结果。</returns>
    private static ParseResult ParseResult(RootCommand root)
    {
        var args = Environment.GetCommandLineArgs().Skip(1).ToArray();
        if (args?.Length is 0 or null)
        {
            args = ["--help"];
        }
        var parseResult = root.Parse(args, new ParserConfiguration()
        {
            EnablePosixBundling = true,
        });
        return parseResult;
    }

    /// <summary>
    /// 同步执行 <see cref="RootCommand"/>，根据返回值决定是否退出进程。
    /// </summary>
    /// <param name="root">根命令对象。</param>
    public static void Invoke(this RootCommand root)
    {
        var parseResult = ParseResult(root);
        var num = parseResult.Invoke();
        if (num == 0)
        {
            return;
        }
        Environment.Exit(num);
    }
}